package com.mallcai.bigdata.ladon.service.report.impl.handler;

import com.alibaba.fastjson.JSON;
import com.cake.bigdata.starter.exception.category.BusinessException;
import com.mallcai.bigdata.ladon.dpl.entity.report.QueryField;
import com.mallcai.bigdata.ladon.dpl.vo.DataType;
import com.mallcai.bigdata.ladon.dpl.vo.QueryFieldType;
import com.mallcai.bigdata.ladon.service.report.impl.ReportQueryConstants;
import com.mallcai.bigdata.ladon.service.report.impl.ReportQueryContext;
import com.mallcai.bigdata.ladon.service.report.impl.handler.support.ParamValueConverter;
import com.mallcai.bigdata.ladon.utils.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 该处理器用来转换客户端传递过来的参数,如果客户端传过来的参数的类型和数据库的配置不一致,则会报错
 * 该处理器之后,客户端传递过来的参数已被格式化
 * 如果是非多选参数,格式为paramName:obj
 * 如果是多选参数,格式为paramName:[obj]
 * @author feixy
 * @version 1.0
 * @date 2019-07-22 09:45
 */
@Slf4j
@Component
@Order(3500)
public class ConvertOriginQueryParamHandler extends AbstractReportQueryPreHandler  {

    @Override
    public void preInternal(ReportQueryContext context) {
        Map<String, Object> originalParams = context.getOriginalParams();
        List<QueryField> queryFields = context.getInnerParam(ReportQueryConstants.KEY_QUERY_FIELDS);
        Map<String, QueryField> queryFieldMap = CollectionUtils.toMap(queryFields, QueryField::getQueryName, Function.identity());
        if (CollectionUtils.isNotEmpty(originalParams)){
            originalParams.forEach((key, val)-> originalParams.put(key,
                    convertSingleParam(key, val, queryFieldMap.get(key))));
        }
    }

    private Object convertSingleParam(String key, Object val, QueryField queryField){
        if (queryField == null){
            return val;
        }
        if(val != null){
            DataType dataType = DataType.getByCode(queryField.getDataType());
            if(dataType == null){
                throw new BusinessException(String.format("非法的参数:参数名称[%s]配置的类型[%s]不支持", key, queryField.getDataType()));
            }
            try{
                if (val instanceof Collection){
                    val = ((Collection<?>) val).stream()
                            .map(v -> ParamValueConverter.convertIfNecessary(v, dataType)).collect(Collectors.toList());
                } else if (val instanceof String && QueryFieldType.MULTIPLE.isSupport(queryField.getType()) ) {
                    val = JSON.parseArray(((String) val).trim()).stream().filter(Objects::nonNull).map(String::valueOf)
                            .map(String::trim).map(v -> ParamValueConverter.convertIfNecessary(v, dataType))
                            .collect(Collectors.toList());
                } else {
                    val = ParamValueConverter.convertIfNecessary(val, dataType);
                }
            }catch (Exception e){
                throw new BusinessException(String.format("非法的参数:参数名称[%s]对应的值数据类型出错",key));
            }
        }
        return val;
    }


}
